-----------------Arena-----------------
A 4am crack                  2017-01-10
---------------------------------------

Name: Arena
Genre: arcade
Year: 1984
Authors: Robert Wray
Publisher: Border Software
Platform: Apple ][+ or later
Media: single-sided 5.25-inch floppy
OS: DOS 3.3
Previous cracks: none

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  immediate disk read error

Locksmith Fast Disk Backup
  unable to read anything other than
  track $00

EDD 4 bit copy (no sync, no count)
  works

Passport (2016-12-30)
  Log:

                 --v--

READING FROM S6,D1
T00,S00 FOUND DOS 3.3 BOOTLOADER
USING DISK'S OWN RWTS
WRITING TO S5,D2

THE DISK WAS COPIED SUCCESSFULLY, BUT
PASSPORT DID NOT APPLY ANY PATCHES.

POSSIBLE REASONS:
- THE SOURCE DISK IS NOT COPY PROTECTED
- THE TARGET DISK WORKS WITHOUT PATCHES
- THE DISK USES AN UNKNOWN PROTECTION,
  AND PASSPORT CAN NOT HELP ANY FURTHER

                 --^--

Passport was able to use the disk's own
RWTS to read the disk and convert all
the sectors to a standard format, but
it didn't find any known protection
routines or RWTS patches. The copy it
produces grinds while loading DOS, so
let's try to find the difference.

                   ~

               Chapter 1
  In Which We Suffer Through The Fact
 That I Am Not Using A IIgs (Hi LoGo!)
   And Need To Use The Inferior //e
           Monitor Commands


Looking through the unprotected track
$00, I see a DOS-shaped RWTS, but I
don't see any obvious differences.
Sector 0 is completely normal. Sector 1
seems normal as well. The RWTS uses
standard entry points -- $B7B5 calls
$BD00 to read a sector, $B793 uses a
loop to read multiple sectors, and so
forth. There's no code at $BB00. None
of the usual suspects.

So here's the plan: capture the RWTS
from the protected disk, then compare
it to the RWTS from an unprotected
disk.

[S5,D1=work disk]

]PR#5
...

]CALL -151

*9600<C600.C6FFM

; set up a callback after early boot
; loads the RWTS into memory
96F8-   A9 4C       LDA   #$4C
96FA-   8D 4A 08    STA   $084A
96FD-   A9 0A       LDA   #$0A
96FF-   8D 4B 08    STA   $084B
9702-   A9 97       LDA   #$97
9704-   8D 4C 08    STA   $084C

; start the boot
9707-   4C 01 08    JMP   $0801

; (callback is here)
; copy the RWTS to lower memory so it
; survives a reboot
970A-   A2 08       LDX   #$08
970C-   A0 00       LDY   #$00
970E-   B9 00 B8    LDA   $B800,Y
9711-   99 00 38    STA   $3800,Y
9714-   C8          INY
9715-   D0 F7       BNE   $970E
9717-   EE 10 97    INC   $9710
971A-   EE 13 97    INC   $9713
971D-   CA          DEX
971E-   D0 EE       BNE   $970E

; turn off the slot 6 drive motor
9720-   AD E8 C0    LDA   $C0E8

; reboot to my work disk in slot 5
9723-   4C 00 C5    JMP   $C500

*BSAVE TRACE,A$9600,L$126
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE RWTS,A$3800,L$800

Excellent! I have the protected RWTS in
memory and saved as a file on disk. Now
I need something to compare it to.

[S6,D1=DOS 3.3 system master]

]PR#6
...

]CALL -151

; copy the standard DOS 3.3 RWTS to
; lower memory so it survives a reboot
*4800<B800.BFFFM

; reboot to my work disk
*C500G
...

; save the standard RWTS from DOS 3.3
]BSAVE DOS 3.3 RWTS,A$4800,L$800

; load the RWTS from the protected disk
]BLOAD RWTS,A$3800

]CALL -151

The Apple //e monitor has a "V" command
to check for differences between memory
ranges. It is very simple and has a
minimal UI (for example, no paging --
it just scrolls everything off the
screen as fast as possible if it finds
more than a screenful of differences),
but it will be good enough for this
purpose.

*3800<4800.48FFV

No differences in this page.

*3900<4900.49FFV

49FD-00 (AA)
49FE-00 (A0)
49FF-00 (A0)

This difference is inconsequential. (It
is unused space, not executable code.)

*3A00<4A00.4AFFV

There is different code at offset $69,
but the code is in my copy of DOS 3.3,
not the protected disk. (This is a
patch that was added to a later version
of DOS 3.3.) There is no code present
on the protected disk, so this is a red
herring.

The next $156 bytes are unused by DOS;
they serve as a temporary buffer during
disk operations. The protected disk has
no code here.

It went on like this for a while. I'll
cut to the chase: I found a key
difference at $BE5A.

*3E00<4E00.4EFFV

4E5A-48 (C9)
4E5B-A0 (23)
4E5C-01 (B0)
4E5D-B1 (EB)
4E5E-3C (0A)
4E5F-6A (20)
4E60-68 (6C)
4E61-90 (BF)
4E62-08 (EA)
4E63-0A (EA)
...

And this is where it gets interesting.

                   ~

               Chapter 2
     In Which It Gets Interesting


Here is $BE5A on the protected disk (in
memory at $3E5A, so everything is off
by whatever that offset is, $8000 or
something):

*3E5AL

3E5A-   C9 23       CMP   #$23
3E5C-   B0 EB       BCS   $3E49
3E5E-   0A          ASL
3E5F-   20 6C BF    JSR   $BF6C
3E62-   EA          NOP
3E63-   EA          NOP

By contrast, DOS 3.3 has completely
different code at $BE5A:

*4E5AL

4E5A-   48          PHA
4E5B-   A0 01       LDY   #$01
4E5D-   B1 3C       LDA   ($3C),Y
4E5F-   6A          ROR
4E60-   68          PLA
4E61-   90 08       BCC   $4E6B
4E63-   0A          ASL

So what's at $BF6C? I bet it's an RWTS
patcher.

*3F6CL

; The current track number is in the
; accumulator at this point, so we're
; skipping ahead if and only if we're
; on track $00 -- the only track that
; was unprotected.
3F6C-   F0 09       BEQ   $3F77

; On all other tracks, fall through to
; here.
3F6E-   09 01       ORA   #$01
3F70-   48          PHA

; (more on this in a minute)
3F71-   20 FC BE    JSR   $BEFC
3F74-   68          PLA

; This is actually an unconditional
; branch because of the "ORA #$01" we
; did earlier (at $BF6E).
3F75-   D0 05       BNE   $3F7C

; This is the branch for track $00 --
; call a completely different routine,
; on which more shortly.
3F77-   20 34 BF    JSR   $BF34
3F7A-   A9 00       LDA   #$00
3F7C-   60          RTS

So $BF34 is called for track $00, and
$BEFC is called for all other tracks.

*3EFCL

3EFC-   A9 D8       LDA   #$D8
3EFE-   20 AF BE    JSR   $BEAF
3F01-   A9 BA       LDA   #$BA
3F03-   20 B6 BE    JSR   $BEB6
3F06-   A0 A9       LDY   #$A9
3F08-   20 BD BE    JSR   $BEBD
3F0B-   A9 DA       LDA   #$DA
3F0D-   20 C4 BE    JSR   $BEC4
3F10-   A9 BA       LDA   #$BA
3F12-   20 CB BE    JSR   $BECB
3F15-   A9 D7       LDA   #$D7
3F17-   20 D2 BE    JSR   $BED2
3F1A-   A9 BB       LDA   #$BB
3F1C-   20 D9 BE    JSR   $BED9
3F1F-   A9 96       LDA   #$96
3F21-   20 E0 BE    JSR   $BEE0
3F24-   A9 D9       LDA   #$D9
3F26-   20 E7 BE    JSR   $BEE7
3F29-   A9 AB       LDA   #$AB
3F2B-   20 EE BE    JSR   $BEEE
3F2E-   A9 EF       LDA   #$EF
3F30-   20 F5 BE    JSR   $BEF5
3F33-   60          RTS

And for track $00:

*3F34L

3F34-   A9 D5       LDA   #$D5
3F36-   20 AF BE    JSR   $BEAF
3F39-   A9 AA       LDA   #$AA
3F3B-   20 B6 BE    JSR   $BEB6
3F3E-   A9 AD       LDA   #$AD
3F40-   20 BD BE    JSR   $BEBD
3F43-   A9 DE       LDA   #$DE
3F45-   20 C4 BE    JSR   $BEC4
3F48-   A9 AA       LDA   #$AA
3F4A-   20 CB BE    JSR   $BECB
3F4D-   A9 D5       LDA   #$D5
3F4F-   20 D2 BE    JSR   $BED2
3F52-   A9 AA       LDA   #$AA
3F54-   20 D9 BE    JSR   $BED9
3F57-   A9 96       LDA   #$96
3F59-   20 E0 BE    JSR   $BEE0
3F5C-   A9 DE       LDA   #$DE
3F5E-   20 E7 BE    JSR   $BEE7
3F61-   A9 AA       LDA   #$AA
3F63-   20 EE BE    JSR   $BEEE
3F66-   A9 FF       LDA   #$FF
3F68-   20 F5 BE    JSR   $BEF5
3F6B-   60          RTS

Well, just by looking at the sequence
of values, I can guess what each of
those subroutines do. They're setting
the address prologue and epilogue, then
the data prologue and epilogue, then
some other RWTS internals.

*3EAFL

; data prologue
3EAF-   8D 53 B8    STA   $B853
3EB2-   8D E7 B8    STA   $B8E7
3EB5-   60          RTS
3EB6-   8D 58 B8    STA   $B858
3EB9-   8D F1 B8    STA   $B8F1
3EBC-   60          RTS
3EBD-   8D 5D B8    STA   $B85D
3EC0-   8D FC B8    STA   $B8FC
3EC3-   60          RTS

; data epilogue
3EC4-   8D 9E B8    STA   $B89E
3EC7-   8D 35 B9    STA   $B935
3ECA-   60          RTS
3ECB-   8D A3 B8    STA   $B8A3
3ECE-   8D 3F B9    STA   $B93F
3ED1-   60          RTS

; address prologue
3ED2-   8D 55 B9    STA   $B955
3ED5-   8D 7A BC    STA   $BC7A
3ED8-   60          RTS
3ED9-   8D 5F B9    STA   $B95F
3EDC-   8D 7F BC    STA   $BC7F
3EDF-   60          RTS
3EE0-   8D 6A B9    STA   $B96A
3EE3-   8D 84 BC    STA   $BC84
3EE6-   60          RTS

; address epilogue
3EE7-   8D 91 B9    STA   $B991
3EEA-   8D AE BC    STA   $BCAE
3EED-   60          RTS
3EEE-   8D 9B B9    STA   $B99B
3EF1-   8D B3 BC    STA   $BCB3
3EF4-   60          RTS

; sync nibble to use between sectors
3EF5-   8D 60 BC    STA   $BC60
3EF8-   8D 3E B8    STA   $B83E
3EFB-   60          RTS

Backtracking, I don't care about any of
this specifically. I should be able to
restore the code at the caller ($BE5A)
to match standard DOS 3.3. Without the
initial call to $BF6C, we'll never
reach either RWTS swapper ($BEFC or
$BF34). We'll just use the RWTS as it's
stored on disk, which already matches
DOS 3.3 and can read the non-working
but standard format copy that Passport
produced.

Using my trusty Disk Fixer sector
editor:

[S6,D1=non-working copy]

T00,S08,$5A:
  C923B0EB0A206CBFEAEA ->
  48A001B13C6A6890080A

]PR#6
...works, and it is glorious...

Quod erat liberandum.

                   ~

               Epilogue


Note to self: if I find any other disks
with this same protection, it would be
easy enough to add support for it to
Passport. The code at $BE5A can serve
as the marker. Passport can patch it to
match DOS 3.3, as I did here by hand.

---------------------------------------
A 4am crack                     No. 952
------------------EOF------------------
